<?php

/**
 * Static class for interacting with MySQL database
 * using mysqli libraries for php
 *
 * @author silentium
 * @license GPLv2
 * @static
 * @global
 */
class MySQL {
  /**
   * MySQL server host
   * @staticvar string $host
   * MySQL server login
   * @staticvar string $user
   * MySQL server password
   * @staticvar string $pwd
   * MySQL database name
   * @staticvar string $db
   */
  public static $host, $user, $pwd, $db;
  /**
   * db queries counter
   * @staticvar int $count
   */
  public static $count=0;
  /**
   * MySQL connection resource
   * @staticvar mysqli $conn
   * MySQL error message
   * @staticvar string $error
   * last executed query
   * @staticvar $last
   */
  public static $conn, $error, $last;
  public static $log = array();
  
  /**
   * Connect to MySQL database
   * @return bool
   */
  public static function connect() {
    self::$conn = mysqli_connect( self::$host, self::$user, self::$pwd, self::$db );
    if ( mysqli_connect_error() ) {
      return false;
    }
    return true;
  }
  
  
  /**
   * close connection to the database
   * @return void
   */
  public static function close() {
    if ( is_resource( self::$conn ) ) {
      mysqli_close( self::$conn );
    }
  }
  
  
  /**
   * Exectute query to the database
   * @param string $sql
   * @return MySQL_Result Query result
   */
  public static function q( $sql ) {
    // query parameters
    $vals = func_get_args();
    
    // inserting parameters into #
    for ( $i=1 ; isset($vals[$i]) && ( $n=strpos( $sql, '#') ) !== false ; $i++ ) {
      $s1 = substr( $sql, 0, $n );
      $s2 = substr( $sql, $n+1 );
       // insert escaped value
      $sql = $s1 . addslashes($vals[$i]) . $s2;
    }
    
    // inserting parameters into :n
    $vals = array_reverse( $vals, true );
    foreach ( $vals as $key => $val ) {
      if ( $key ) { // there is query string at zero index, don't need that
        // insert escaped value at :$key
        $sql = str_replace( ':'.$key, addslashes($val), $sql );
      }
    }
    // save a copy of last query for debug purposes
    self::$last = $sql;
    defined('DEBUG') && array_push( self::$log, $sql );
    // split queries by delimiter (may be several queries)
    $sql = explode( ";;\n", $sql );
    self::$error = '';
    foreach ( $sql as $q ) {
      //execute query
      $res = mysqli_query( self::$conn, $q );
      // save an error message for debug purposes
      self::$error .= mysqli_error( self::$conn ) . "\n";
      // inc query counter
      ++self::$count;
    }
    return new MySQL_Result( $res );
  }
  
  
  /**
   * wrapper for q($sql) method
   * @param string $sql
   * @return MySQL_Result Query result
   */
  public static function query( $sql ) {
    return self::q( $sql );
  }
  

  /**
   * identifier of last inserted row
   * @return int
   */
  public static function inserted() {
    return mysqli_insert_id( self::$conn );
  }

  /**
   * Connection status. True if connected.
   * @return bool
   */
  public static function ok() {
    return is_a( self::$conn, 'mysqli' );
  }
  
  
  /**
   * Connection status. True if connected.
   * @return bool
   */
    public static function connected() {
    return is_a( self::$conn, 'mysqli' );
  }
  


  /**
   * Delete row by $id from $table
   * @param string $table
   * @param int $id
   * @return bool
   */
  public static function delete( $table, $id ) {
  	return self::q( "DELETE FROM `".$table."` WHERE `id`=':1'", $id ) ;
  }
  
  
}




/**
 * MySQLi result handler class
 */
class MySQL_Result extends Vector {
  /**
   * Result resourse
   * @var mysqli_result $res
   */
  private $res=false;
  /**
   * Result rows
   * @var array $items
   */
  protected $items=array();
  /**
   * number of result rows
   * @var integer $num
   */
  private $num = 0;
  /**
   * cursor for rows
   * @var integer $cursor
   */
  private $cursor=0;
  
  /**
   * class constructor.
   * Determine query success. Fetch rows, if they exist.
   * @param mysqli_result $res
   */
  public function __construct($res) {
    if ( is_a( $res, 'mysqli_result' ) ) {
      for ( $this->num=0 ; $this->items[] = mysqli_fetch_assoc($res); $this->num++ ) {}
      array_pop( $this->items );
      mysqli_free_result($res);
    } elseif ( $res===true ) {
      $this->items = true;
    }
  }
  
/**
 * method with questionable benefit
 */
  public function __toString() {
    if ( is_array( $this->res ) ) {
      return 'Resource';
    } else {
      return '';
    }
  }
  
  
  /**
   * wrapper for success() method. exists for compatibility.
   * @return bool
   */
  public function ready() {
    return $this->success();
  }
  
  /**
   * check if query succeeded
   * @return bool
   */
  public function success() {
    if ( $this->num || $this->items===true ) {
  	  return true;
  	} else {
  	  return false;
  	}
  }
  
  
  
  /**
   * check if row at cursor exists
   * @return bool
   */
  public function exists() {
    return $this->cursor < $this->num && $this->cursor >= 0;
  }
  
  
  
  /**
   * Return result rows count
   * @return int
   */
  public function num() {
    return $this->num;
  }
  

  /**
   * Return result row as numerated array
   * @return array
   */
  public function row() {
    $res = false;
    if ( $this->exists() ) {
      $res = array();
      foreach ( $this->items[$this->cursor] as $val ) {
        $res[] = $val;
      }
    }
    ++$this->cursor;
    return $res;
  }
  
  
  /**
   * Return result row a associative array field => value
   * @return assoc_array
   */
  public function assoc() {
    if ( $this->exists() ) {
      return $this->items[$this->cursor++];
    } else {
      return false;
    }
  }
  
  
  /**
   * Return $field value of current row
   * @param string $field
   * @return mixed
   */
  public function get($field) {
    if ( $this->exists() ) {
      return $this->items[$this->cursor++][$field];
    }
    return false;
  }
  
    
  /**
   * Return values of $field as array
   * @param string $field
   * @return array
   */
  public function get_array($field) {
    if ( $this->num ) {
      $a = array();
      foreach ( $this->items as $res ) {
        $a[] = $res[$field];
      }
      return $a;
    } else {
      return false;
    }
  }
  
  
  /**
   * Return rows or values of $field as array
   * @param string[optional] $field
   * @return array
   */
    public function arr( $field=null ) {
    if ( $this->num ) {
      return $field ? $this->get_array($field) : $this->items;
    } else {
      return false;
    }
  }
  

  /**
   * Switch to the next row
   * @return MySQL_Result
   */
  public function next() {
    if ( $this->exists() ) {
      ++$this->cursor;
    }
    return $this;
  }

  
  /**
   * Switch to the previous row
   * @return MySQL_Result
   */
  public function prev() {
    if ( $this->exists() ) {
      --$this->cursor;
    }
    return $this;
  }


  /**
   * Switch to the last row
   * @return MySQL_Result
   */
  public function last() {
    $this->cursor = $this->num-1;
    return $this;
  }
  
  
  /**
   * Switch to the first row
   * @return MySQL_Result
   */
  public function first() {
    $this->cursor = 0;
    return $this;
  }
  
  
  public function __get( $name ) {
    return $this->items[$this->cursor][$name];
  }
  public function __set( $name, $value ) {
    return $this->items[$this->cursor][$name] = $value;
  }
  
}



?>